using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
using System;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using EntityKit.Runtime;

namespace EntityKit.Editor
{
    /// <summary>
    /// Excel转代码工具
    /// </summary>
    public static class ExcelCodeGenerator
    {
        #region Public Methods
        
        /// <summary>
        /// 生成代码
        /// </summary>
        public static void GenerateCode(List<string> excelFiles, string outputPath)
        {
            if (excelFiles.Count == 0)
            {
                EditorUtility.DisplayDialog("提示", "未发现xlsx文件，请注意不是xls", "确定");
                return;
            }

            //同名文件判断
            var fileNameList = excelFiles.Select((s) => Path.GetFileName(s).ToLower()).ToList();
            foreach (var fileName in fileNameList)
            {
                var duplicates = fileNameList.FindAll((f) => f == fileName);
                if (duplicates.Count > 1)
                {
                    EditorUtility.DisplayDialog("提示", "表名 字段名不区分大小写,请处理重名exel! ->" + fileName, "OK");
                    return;
                }
            }

            //导出excel
            foreach (var file in excelFiles)
            {
                GenerateClassFromExcel(outputPath, file);
            }
            
            AssetDatabase.Refresh();
        }

        /// <summary>
        /// 通过excel生成class
        /// </summary>
        /// <param name="outputDirectory">输出目录</param>
        /// <param name="excelFilePath">Excel文件路径</param>
        public static void GenerateClassFromExcel(string outputDirectory, string excelFilePath)
        {
            Debug.LogFormat("[{0}]正在生成：", excelFilePath);
            var excelConverter = new ExcelConverter(excelFilePath);
            int idColumnIndex = -1;
            int idRowIndex = -1;
            string json = excelConverter.ConvertToJsonString(ref idColumnIndex, ref idRowIndex);
            
            if (idColumnIndex != -1 && idRowIndex != -1)
            {
                if (idRowIndex < 2)
                {
                    Debug.LogErrorFormat("【生成失败】 {0} ,请检查表头预留3行:备注，类型，字段名!", Path.GetFileName(excelFilePath));
                    return;
                }

                //这里将前三列进行判断
                var statements = excelConverter.GetRowData(idRowIndex - 2);
                var fieldTypes = excelConverter.GetRowData(idRowIndex - 1);
                if (idColumnIndex > 0)
                {
                    statements.RemoveRange(0, idColumnIndex);
                    fieldTypes.RemoveRange(0, idColumnIndex);
                }

                var classContent = ConvertJsonToClass(excelFilePath, json, statements, fieldTypes);

                //输出目录控制
                string outputFile = Path.Combine(outputDirectory, Path.GetFileNameWithoutExtension(excelFilePath) + ".cs");

                if (File.Exists(outputFile))
                {
                    File.Delete(outputFile);
                }

                FileHelper.WriteTextFile(outputFile, classContent);
                Debug.LogFormat("<color=green> [成功] </color>：{0}", excelFilePath);
            }
            else
            {
                Debug.LogError("不符合规范内容:" + excelFilePath);
            }
        }
        
        #endregion
        
        #region Private Methods
        
        /// <summary>
        /// 将JSON转换为C#类
        /// 自动分析字段
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="json">JSON字符串</param>
        /// <param name="statements">注释</param>
        /// <param name="fieldTypes">字段类型</param>
        /// <returns>C#类代码</returns>
        private static string ConvertJsonToClass(string fileName, string json, List<object> statements, List<object> fieldTypes)
        {
            string className = Path.GetFileNameWithoutExtension(fileName);
            
            //生成类服务
            ExcelClassTemplate excelClassTemplate = new ExcelClassTemplate(className);
            var jsonData = JsonMapper.ToObject(json)[0];
            int i = 0;
            IDictionary dict = jsonData as IDictionary;
            
            foreach (string key in dict.Keys)
            {
                //字段
                string attribute = "";
                if (key.ToLower() == "id" && key != "ID")
                {
                    Debug.LogErrorFormat("<color=yellow>表格{0}字段必须为ID[大小写区分],请修改后生成</color>", className);
                    break;
                }
                else if (key == "ID")
                {
                    //增加一个sqlite主键
                    //attribute = "PrimaryKey";
                    i++;
                    continue;
                }

                string type = null;
                if (fieldTypes != null && fieldTypes.Count >= jsonData.Count)
                {
                    type = fieldTypes[i].ToString();
                }

                //添加字段
                excelClassTemplate.AddField(statements[i].ToString(), attribute, type, key);
                i++;
            }

            //生成代码       
            return excelClassTemplate.GenerateClass();
        }
        
        #endregion
    }

    /// <summary>
    /// Excel转class 模板
    /// </summary>
    public class ExcelClassTemplate
    {
        #region Fields
        
        public string ClassTemplate = @"
//------------------------------------------------------------------------------
// <auto-generated>
//    由模板自动生成,请勿修改
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;

namespace EntityKit.Runtime
{
    [Serializable]
    public class [ClassName] : ConfigTableBase
    {
        [Fields]
    }
}";

        public string FieldWithAttributeTemplate = @"
        /// <summary>
        /// [Statement]
        /// </summary>
        [Attribute]
        public [Type] [Name] { get; set; }";

        public string FieldWithoutAttributeTemplate = @"
        /// <summary>
        /// [Statement]
        /// </summary>
        public [Type] [Name] { get; set; }";

        private string mClassName = "NoName";
        private string mFieldContents = "";
        
        #endregion
        
        #region Constructor
        
        public ExcelClassTemplate(string className)
        {
            this.mClassName = className;
        }
        
        #endregion
        
        #region Public Methods
        
        /// <summary>
        /// 添加字段
        /// </summary>
        /// <param name="statement">注释</param>
        /// <param name="attribute">属性</param>
        /// <param name="type">类型</param>
        /// <param name="fieldName">字段名</param>
        public void AddField(string statement, string attribute, string type, string fieldName)
        {
            string fieldTemplate = "";
            if (string.IsNullOrEmpty(attribute))
            {
                fieldTemplate = this.FieldWithoutAttributeTemplate;
            }
            else
            {
                fieldTemplate = this.FieldWithAttributeTemplate;
            }

            fieldTemplate = fieldTemplate.Replace("[Statement]", statement);
            if (!string.IsNullOrEmpty(attribute))
            {
                fieldTemplate = fieldTemplate.Replace("[Attribute]", $"[{attribute}]");
            }

            fieldTemplate = fieldTemplate.Replace("[Type]", type);
            fieldTemplate = fieldTemplate.Replace("[Name]", fieldName);

            this.mFieldContents += fieldTemplate;
        }

        /// <summary>
        /// 生成类代码
        /// </summary>
        /// <returns>类代码</returns>
        public string GenerateClass()
        {
            this.ClassTemplate = ClassTemplate.Replace("[ClassName]", mClassName).Replace("[Fields]", mFieldContents);
            return this.ClassTemplate;
        }
        
        #endregion
    }
}